package com.derbysoft.synxisadapter.dswitch3.service.impl;

import com.derbysoft.dswitch.remote.hotel.dto.HotelCancelRequest;
import com.derbysoft.dswitch.remote.hotel.dto.HotelCancelResponse;
import com.derbysoft.synxisadapter.commons.dto.synxis.OTACancelRQ;
import com.derbysoft.synxisadapter.commons.dto.synxis.OTACancelRS;
import com.derbysoft.synxisadapter.commons.model.Channel;
import com.derbysoft.synxisadapter.commons.model.Reservation;
import com.derbysoft.synxisadapter.commons.repository.ReservationRepository;
import com.derbysoft.synxisadapter.commons.utils.ErrorMessageUtils;
import com.derbysoft.synxisadapter.dswitch2.translator.Translator;
import com.derbysoft.synxisadapter.dswitch3.service.HotelProviderService;
import com.derbysoft.synxisadapter.webservice.SynXisWebService;
import com.derbysoft.synxisadapter.webservice.impl.ResponsePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * User: jason
 * Date: 2012-11-21
 */
@Component("ds3CancelService")
public class CancelServiceImpl extends DS3AbstractService
        implements HotelProviderService<HotelCancelRequest, HotelCancelResponse> {

    private static Logger logger = LoggerFactory.getLogger(CancelServiceImpl.class);

    @Autowired
    @Qualifier("cancellationWebService")
    private SynXisWebService<OTACancelRQ, OTACancelRS> cancellationWebService;

    @Autowired
    @Qualifier("ds3CancelRQTranslator")
    private Translator<HotelCancelRequest, List<OTACancelRQ>, Void> ds3CancelTranslator;

    @Autowired
    @Qualifier("ds3CancelRSTranslator")
    private Translator<List<ResponsePair<OTACancelRQ, OTACancelRS>>, HotelCancelResponse, String> ds3CancelRSTranslator;

    @Autowired
    private ReservationRepository reservationRepository;

    @Override
    public HotelCancelResponse execute(HotelCancelRequest request) {
        try {
            Channel channel = loadChannel(request.getHeader().getSource());
            List<OTACancelRQ> otaCancelRQs = ds3CancelTranslator.translate(request, null);

            List<ResponsePair<OTACancelRQ, OTACancelRS>> responsePairs = cancellationWebService.batchInvoke(otaCancelRQs,channel);

            HotelCancelResponse response = ds3CancelRSTranslator.translate(responsePairs, request.getHeader().getTaskId());

            if (response.getError() != null) {
                reservationRepository.updateStatus(request.getHotelCancelRQ().getErsp(), Reservation.Status.CANCEL_FAILED);
                return response;
            }

            reservationRepository.updateStatus(request.getHotelCancelRQ().getErsp(), Reservation.Status.CANCELLED);

            saveCancelNumbers(request.getHotelCancelRQ().getErsp(), responsePairs);

            return response;
        } catch (Exception ex) {
            logger.error(ErrorMessageUtils.buildErrorMessage(ex));
            return createErrorResponse(request, ex);
        }
    }

    private void saveCancelNumbers(String ersp, List<ResponsePair<OTACancelRQ, OTACancelRS>> responsePairs) {
        for (ResponsePair<OTACancelRQ, OTACancelRS> responsePair : responsePairs) {
            String confirmNumber = responsePair.getRequest().getUniqueID().get(0).getID();
            String cancelNumber = responsePair.getResponse().getUniqueID().get(0).getID();
            reservationRepository.cancel(ersp, confirmNumber, cancelNumber);
        }
    }

    private HotelCancelResponse createErrorResponse(HotelCancelRequest request, Exception ex) {
        HotelCancelResponse response = new HotelCancelResponse();
        response.setTaskId(request.getHeader().getTaskId());
        response.setError(createDS3ErrorDTO(ex));
        return response;
    }
}